home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / perl / sprite / RCS / perl.c,v < prev    next >
Encoding:
Text File  |  1991-11-14  |  37.1 KB  |  1,538 lines

  1. head     1.3;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.3
  10. date     91.11.14.12.52.07;  author jhh;  state Exp;
  11. branches ;
  12. next     1.2;
  13.  
  14. 1.2
  15. date     91.07.16.17.03.10;  author jhh;  state Exp;
  16. branches ;
  17. next     1.1;
  18.  
  19. 1.1
  20. date     91.07.16.12.16.14;  author jhh;  state Exp;
  21. branches ;
  22. next     ;
  23.  
  24.  
  25. desc
  26. @@
  27.  
  28.  
  29. 1.3
  30. log
  31. @patchlevel 19
  32. @
  33. text
  34. @char rcsid[] = "$RCSfile: perl.c,v $$Revision: 1.2 $$Date: 91/07/16 17:03:10 $\nPatch level: ###\n";
  35. /*
  36.  *    Copyright (c) 1991, Larry Wall
  37.  *
  38.  *    You may distribute under the terms of either the GNU General Public
  39.  *    License or the Artistic License, as specified in the README file.
  40.  *
  41.  * $Log:    perl.c,v $
  42.  * Revision 4.0.1.6  91/11/11  16:38:45  lwall
  43.  * patch19: default arg for shift was wrong after first subroutine definition
  44.  * patch19: op/regexp.t failed from missing arg to bcmp()
  45.  * 
  46.  * Revision 4.0.1.5  91/11/05  18:03:32  lwall
  47.  * patch11: random cleanup
  48.  * patch11: $0 was being truncated at times
  49.  * patch11: cppstdin now installed outside of source directory
  50.  * patch11: -P didn't allow use of #elif or #undef
  51.  * patch11: prepared for ctype implementations that don't define isascii()
  52.  * patch11: added eval {}
  53.  * patch11: eval confused by string containing null
  54.  *
  55.  * Revision 1.2  91/07/16  17:03:10  jhh
  56.  * we use some sort of non-standard sed
  57.  * 
  58.  * Revision 1.1  91/07/16  12:16:14  jhh
  59.  * Initial revision
  60.  * 
  61.  * Revision 4.0.1.4  91/06/10  01:23:07  lwall
  62.  * patch10: perl -v printed incorrect copyright notice
  63.  * 
  64.  * Revision 4.0.1.3  91/06/07  11:40:18  lwall
  65.  * patch4: changed old $^P to $^X
  66.  * 
  67.  * Revision 4.0.1.2  91/06/07  11:26:16  lwall
  68.  * patch4: new copyright notice
  69.  * patch4: added $^P variable to control calling of perldb routines
  70.  * patch4: added $^F variable to specify maximum system fd, default 2
  71.  * patch4: debugger lost track of lines in eval
  72.  * 
  73.  * Revision 4.0.1.1  91/04/11  17:49:05  lwall
  74.  * patch1: fixed undefined environ problem
  75.  * 
  76.  * Revision 4.0  91/03/20  01:37:44  lwall
  77.  * 4.0 baseline.
  78.  * 
  79.  */
  80.  
  81. /*SUPPRESS 560*/
  82.  
  83. #include "EXTERN.h"
  84. #include "perl.h"
  85. #include "perly.h"
  86. #ifdef MSDOS
  87. #include "patchlev.h"
  88. #else
  89. #include "patchlevel.h"
  90. #endif
  91.  
  92. char *getenv();
  93.  
  94. #ifdef IAMSUID
  95. #ifndef DOSUID
  96. #define DOSUID
  97. #endif
  98. #endif
  99.  
  100. #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
  101. #ifdef DOSUID
  102. #undef DOSUID
  103. #endif
  104. #endif
  105.  
  106. static char* moreswitches();
  107. static char* cddir;
  108. static bool minus_c;
  109. static char patchlevel[6];
  110. static char *nrs = "\n";
  111. static int nrschar = '\n';      /* final char of rs, or 0777 if none */
  112. static int nrslen = 1;
  113.  
  114. main(argc,argv,env)
  115. register int argc;
  116. register char **argv;
  117. register char **env;
  118. {
  119.     register STR *str;
  120.     register char *s;
  121.     char *scriptname;
  122.     char *getenv();
  123.     bool dosearch = FALSE;
  124. #ifdef DOSUID
  125.     char *validarg = "";
  126. #endif
  127.  
  128. #ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
  129. #ifdef IAMSUID
  130. #undef IAMSUID
  131.     fatal("suidperl is no longer needed since the kernel can now execute\n\
  132. setuid perl scripts securely.\n");
  133. #endif
  134. #endif
  135.  
  136.     origargv = argv;
  137.     origargc = argc;
  138.     origenviron = environ;
  139.     uid = (int)getuid();
  140.     euid = (int)geteuid();
  141.     gid = (int)getgid();
  142.     egid = (int)getegid();
  143.     sprintf(patchlevel,"%3.3s%2.2d", index(rcsid,'4'), PATCHLEVEL);
  144. #ifdef MSDOS
  145.     /*
  146.      * There is no way we can refer to them from Perl so close them to save
  147.      * space.  The other alternative would be to provide STDAUX and STDPRN
  148.      * filehandles.
  149.      */
  150.     (void)fclose(stdaux);
  151.     (void)fclose(stdprn);
  152. #endif
  153.     if (do_undump) {
  154.     origfilename = savestr(argv[0]);
  155.     do_undump = 0;
  156.     loop_ptr = -1;        /* start label stack again */
  157.     goto just_doit;
  158.     }
  159.     (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
  160.     linestr = Str_new(65,80);
  161.     str_nset(linestr,"",0);
  162.     str = str_make("",0);        /* first used for -I flags */
  163.     curstash = defstash = hnew(0);
  164.     curstname = str_make("main",4);
  165.     stab_xhash(stabent("_main",TRUE)) = defstash;
  166.     defstash->tbl_name = "main";
  167.     incstab = hadd(aadd(stabent("INC",TRUE)));
  168.     incstab->str_pok |= SP_MULTI;
  169.     for (argc--,argv++; argc > 0; argc--,argv++) {
  170.     if (argv[0][0] != '-' || !argv[0][1])
  171.         break;
  172. #ifdef DOSUID
  173.     if (*validarg)
  174.     validarg = " PHOOEY ";
  175.     else
  176.     validarg = argv[0];
  177. #endif
  178.     s = argv[0]+1;
  179.       reswitch:
  180.     switch (*s) {
  181.     case '0':
  182.     case 'a':
  183.     case 'c':
  184.     case 'd':
  185.     case 'D':
  186.     case 'i':
  187.     case 'l':
  188.     case 'n':
  189.     case 'p':
  190.     case 'u':
  191.     case 'U':
  192.     case 'v':
  193.     case 'w':
  194.         if (s = moreswitches(s))
  195.         goto reswitch;
  196.         break;
  197.  
  198.     case 'e':
  199. #ifdef TAINT
  200.         if (euid != uid || egid != gid)
  201.         fatal("No -e allowed in setuid scripts");
  202. #endif
  203.         if (!e_fp) {
  204.             e_tmpname = savestr(TMPPATH);
  205.         (void)mktemp(e_tmpname);
  206.         e_fp = fopen(e_tmpname,"w");
  207.         if (!e_fp)
  208.             fatal("Cannot open temporary file");
  209.         }
  210.         if (argv[1]) {
  211.         fputs(argv[1],e_fp);
  212.         argc--,argv++;
  213.         }
  214.         (void)putc('\n', e_fp);
  215.         break;
  216.     case 'I':
  217. #ifdef TAINT
  218.         if (euid != uid || egid != gid)
  219.         fatal("No -I allowed in setuid scripts");
  220. #endif
  221.         str_cat(str,"-");
  222.         str_cat(str,s);
  223.         str_cat(str," ");
  224.         if (*++s) {
  225.         (void)apush(stab_array(incstab),str_make(s,0));
  226.         }
  227.         else if (argv[1]) {
  228.         (void)apush(stab_array(incstab),str_make(argv[1],0));
  229.         str_cat(str,argv[1]);
  230.         argc--,argv++;
  231.         str_cat(str," ");
  232.         }
  233.         break;
  234.     case 'P':
  235. #ifdef TAINT
  236.         if (euid != uid || egid != gid)
  237.         fatal("No -P allowed in setuid scripts");
  238. #endif
  239.         preprocess = TRUE;
  240.         s++;
  241.         goto reswitch;
  242.     case 's':
  243. #ifdef TAINT
  244.         if (euid != uid || egid != gid)
  245.         fatal("No -s allowed in setuid scripts");
  246. #endif
  247.         doswitches = TRUE;
  248.         s++;
  249.         goto reswitch;
  250.     case 'S':
  251. #ifdef TAINT
  252.         if (euid != uid || egid != gid)
  253.         fatal("No -S allowed in setuid scripts");
  254. #endif
  255.         dosearch = TRUE;
  256.         s++;
  257.         goto reswitch;
  258.     case 'x':
  259.         doextract = TRUE;
  260.         s++;
  261.         if (*s)
  262.         cddir = savestr(s);
  263.         break;
  264.     case '-':
  265.         argc--,argv++;
  266.         goto switch_end;
  267.     case 0:
  268.         break;
  269.     default:
  270.         fatal("Unrecognized switch: -%s",s);
  271.     }
  272.     }
  273.   switch_end:
  274.     scriptname = argv[0];
  275.     if (e_fp) {
  276.     (void)fclose(e_fp);
  277.     argc++,argv--;
  278.     scriptname = e_tmpname;
  279.     }
  280.  
  281. #ifdef MSDOS
  282. #define PERLLIB_SEP ';'
  283. #else
  284. #define PERLLIB_SEP ':'
  285. #endif
  286. #ifndef TAINT        /* Can't allow arbitrary PERLLIB in setuid script */
  287.     {
  288.     char * s2 = getenv("PERLLIB");
  289.  
  290.     if ( s2 ) {
  291.         /* Break at all separators */
  292.         while ( *s2 ) {
  293.         /* First, skip any consecutive separators */
  294.         while ( *s2 == PERLLIB_SEP ) {
  295.             /* Uncomment the next line for PATH semantics */
  296.             /* (void)apush(stab_array(incstab),str_make(".",1)); */
  297.             s2++;
  298.         }
  299.         if ( (s = index(s2,PERLLIB_SEP)) != Nullch ) {
  300.             (void)apush(stab_array(incstab),str_make(s2,(int)(s-s2)));
  301.             s2 = s+1;
  302.         } else {
  303.             (void)apush(stab_array(incstab),str_make(s2,0));
  304.             break;
  305.         }
  306.         }
  307.     }
  308.     }
  309. #endif /* TAINT */
  310.  
  311. #ifndef PRIVLIB
  312. #define PRIVLIB "/usr/local/lib/perl"
  313. #endif
  314.     (void)apush(stab_array(incstab),str_make(PRIVLIB,0));
  315.     (void)apush(stab_array(incstab),str_make(".",1));
  316.  
  317.     str_set(&str_no,No);
  318.     str_set(&str_yes,Yes);
  319.  
  320.     /* open script */
  321.  
  322.     if (scriptname == Nullch)
  323. #ifdef MSDOS
  324.     {
  325.     if ( isatty(fileno(stdin)) )
  326.       moreswitches("v");
  327.     scriptname = "-";
  328.     }
  329. #else
  330.     scriptname = "-";
  331. #endif
  332.     if (dosearch && !index(scriptname, '/') && (s = getenv("PATH"))) {
  333.     char *xfound = Nullch, *xfailed = Nullch;
  334.     int len;
  335.  
  336.     bufend = s + strlen(s);
  337.     while (*s) {
  338. #ifndef MSDOS
  339.         s = cpytill(tokenbuf,s,bufend,':',&len);
  340. #else
  341.         for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
  342.         tokenbuf[len] = '\0';
  343. #endif
  344.         if (*s)
  345.         s++;
  346. #ifndef MSDOS
  347.         if (len && tokenbuf[len-1] != '/')
  348. #else
  349.         if (len && tokenbuf[len-1] != '\\')
  350. #endif
  351.         (void)strcat(tokenbuf+len,"/");
  352.         (void)strcat(tokenbuf+len,scriptname);
  353. #ifdef DEBUGGING
  354.         if (debug & 1)
  355.         fprintf(stderr,"Looking for %s\n",tokenbuf);
  356. #endif
  357.         if (stat(tokenbuf,&statbuf) < 0)        /* not there? */
  358.         continue;
  359.         if (S_ISREG(statbuf.st_mode)
  360.          && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
  361.         xfound = tokenbuf;              /* bingo! */
  362.         break;
  363.         }
  364.         if (!xfailed)
  365.         xfailed = savestr(tokenbuf);
  366.     }
  367.     if (!xfound)
  368.         fatal("Can't execute %s", xfailed ? xfailed : scriptname );
  369.     if (xfailed)
  370.         Safefree(xfailed);
  371.     scriptname = savestr(xfound);
  372.     }
  373.  
  374.     fdpid = anew(Nullstab);    /* for remembering popen pids by fd */
  375.     pidstatus = hnew(COEFFSIZE);/* for remembering status of dead pids */
  376.  
  377.     origfilename = savestr(scriptname);
  378.     curcmd->c_filestab = fstab(origfilename);
  379.     if (strEQ(origfilename,"-"))
  380.     scriptname = "";
  381.     if (preprocess) {
  382.     char *cpp = CPPSTDIN;
  383.  
  384.     if (strEQ(cpp,"cppstdin"))
  385.         sprintf(tokenbuf, "%s/%s", SCRIPTDIR, cpp);
  386.     else
  387.         sprintf(tokenbuf, "%s", cpp);
  388.     str_cat(str,"-I");
  389.     str_cat(str,PRIVLIB);
  390. #ifdef sprite
  391.     (void)sprintf(buf, "\
  392. /sprite/cmds/sed -e '/^[^#]/b end' \
  393.  -e '/^#[     ]*include[     ]/b end' \
  394.  -e '/^#[     ]*define[     ]/b end' \
  395.  -e '/^#[     ]*if[     ]/b end' \
  396.  -e '/^#[     ]*ifdef[     ]/b end' \
  397.  -e '/^#[     ]*ifndef[     ]/b end' \
  398.  -e '/^#[     ]*else/b end' \
  399.  -e '/^#[     ]*endif/b end' \
  400.  -e 's/^#.*//' \
  401.  -e ': end' \
  402.  %s | %s -C %s %s",
  403.       argv[0], CPPSTDIN, str_get(str), CPPMINUS);
  404.  
  405. #else
  406.     (void)sprintf(buf, "\
  407. %ssed %s -e '/^[^#]/b' \
  408.  -e '/^#[     ]*include[     ]/b' \
  409.  -e '/^#[     ]*define[     ]/b' \
  410.  -e '/^#[     ]*if[     ]/b' \
  411.  -e '/^#[     ]*ifdef[     ]/b' \
  412.  -e '/^#[     ]*ifndef[     ]/b' \
  413.  -e '/^#[     ]*else/b' \
  414.  -e '/^#[     ]*elif[     ]/b' \
  415.  -e '/^#[     ]*undef[     ]/b' \
  416.  -e '/^#[     ]*endif/b' \
  417.  -e 's/^[     ]*#.*//' \
  418.  %s | %s -C %s %s",
  419. #ifdef MSDOS
  420.       "",
  421. #else
  422.       "/bin/",
  423. #endif
  424.       (doextract ? "-e '1,/^#/d\n'" : ""),
  425.       scriptname, tokenbuf, str_get(str), CPPMINUS);
  426. #ifdef DEBUGGING
  427.     if (debug & 64) {
  428.         fputs(buf,stderr);
  429.         fputs("\n",stderr);
  430.     }
  431. #endif
  432. #endif /*sprite*/
  433.     doextract = FALSE;
  434. #ifdef IAMSUID                /* actually, this is caught earlier */
  435.     if (euid != uid && !euid)    /* if running suidperl */
  436. #ifdef HAS_SETEUID
  437.         (void)seteuid(uid);        /* musn't stay setuid root */
  438. #else
  439. #ifdef HAS_SETREUID
  440.         (void)setreuid(-1, uid);
  441. #else
  442.         setuid(uid);
  443. #endif
  444. #endif
  445. #endif /* IAMSUID */
  446.     rsfp = mypopen(buf,"r");
  447.     }
  448.     else if (!*scriptname) {
  449. #ifdef TAINT
  450.     if (euid != uid || egid != gid)
  451.         fatal("Can't take set-id script from stdin");
  452. #endif
  453.     rsfp = stdin;
  454.     }
  455.     else
  456.     rsfp = fopen(scriptname,"r");
  457.     if ((FILE*)rsfp == Nullfp) {
  458. #ifdef DOSUID
  459. #ifndef IAMSUID        /* in case script is not readable before setuid */
  460.     if (euid && stat(stab_val(curcmd->c_filestab)->str_ptr,&statbuf) >= 0 &&
  461.       statbuf.st_mode & (S_ISUID|S_ISGID)) {
  462.         (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
  463.         execv(buf, origargv);    /* try again */
  464.         fatal("Can't do setuid\n");
  465.     }
  466. #endif
  467. #endif
  468.     fatal("Can't open perl script \"%s\": %s\n",
  469.       stab_val(curcmd->c_filestab)->str_ptr, strerror(errno));
  470.     }
  471.     str_free(str);        /* free -I directories */
  472.     str = Nullstr;
  473.  
  474.     /* do we need to emulate setuid on scripts? */
  475.  
  476.     /* This code is for those BSD systems that have setuid #! scripts disabled
  477.      * in the kernel because of a security problem.  Merely defining DOSUID
  478.      * in perl will not fix that problem, but if you have disabled setuid
  479.      * scripts in the kernel, this will attempt to emulate setuid and setgid
  480.      * on scripts that have those now-otherwise-useless bits set.  The setuid
  481.      * root version must be called suidperl or sperlN.NNN.  If regular perl
  482.      * discovers that it has opened a setuid script, it calls suidperl with
  483.      * the same argv that it had.  If suidperl finds that the script it has
  484.      * just opened is NOT setuid root, it sets the effective uid back to the
  485.      * uid.  We don't just make perl setuid root because that loses the
  486.      * effective uid we had before invoking perl, if it was different from the
  487.      * uid.
  488.      *
  489.      * DOSUID must be defined in both perl and suidperl, and IAMSUID must
  490.      * be defined in suidperl only.  suidperl must be setuid root.  The
  491.      * Configure script will set this up for you if you want it.
  492.      *
  493.      * There is also the possibility of have a script which is running
  494.      * set-id due to a C wrapper.  We want to do the TAINT checks
  495.      * on these set-id scripts, but don't want to have the overhead of
  496.      * them in normal perl, and can't use suidperl because it will lose
  497.      * the effective uid info, so we have an additional non-setuid root
  498.      * version called taintperl or tperlN.NNN that just does the TAINT checks.
  499.      */
  500.  
  501. #ifdef DOSUID
  502.     if (fstat(fileno(rsfp),&statbuf) < 0)    /* normal stat is insecure */
  503.     fatal("Can't stat script \"%s\"",origfilename);
  504.     if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
  505.     int len;
  506.  
  507. #ifdef IAMSUID
  508. #ifndef HAS_SETREUID
  509.     /* On this access check to make sure the directories are readable,
  510.      * there is actually a small window that the user could use to make
  511.      * filename point to an accessible directory.  So there is a faint
  512.      * chance that someone could execute a setuid script down in a
  513.      * non-accessible directory.  I don't know what to do about that.
  514.      * But I don't think it's too important.  The manual lies when
  515.      * it says access() is useful in setuid programs.
  516.      */
  517.     if (access(stab_val(curcmd->c_filestab)->str_ptr,1))    /*double check*/
  518.         fatal("Permission denied");
  519. #else
  520.     /* If we can swap euid and uid, then we can determine access rights
  521.      * with a simple stat of the file, and then compare device and
  522.      * inode to make sure we did stat() on the same file we opened.
  523.      * Then we just have to make sure he or she can execute it.
  524.      */
  525.     {
  526.         struct stat tmpstatbuf;
  527.  
  528.         if (setreuid(euid,uid) < 0 || getuid() != euid || geteuid() != uid)
  529.         fatal("Can't swap uid and euid");    /* really paranoid */
  530.         if (stat(stab_val(curcmd->c_filestab)->str_ptr,&tmpstatbuf) < 0)
  531.         fatal("Permission denied");    /* testing full pathname here */
  532.         if (tmpstatbuf.st_dev != statbuf.st_dev ||
  533.         tmpstatbuf.st_ino != statbuf.st_ino) {
  534.         (void)fclose(rsfp);
  535.         if (rsfp = mypopen("/bin/mail root","w")) {    /* heh, heh */
  536.             fprintf(rsfp,
  537. "User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
  538. (Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
  539.             uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
  540.             statbuf.st_dev, statbuf.st_ino,
  541.             stab_val(curcmd->c_filestab)->str_ptr,
  542.             statbuf.st_uid, statbuf.st_gid);
  543.             (void)mypclose(rsfp);
  544.         }
  545.         fatal("Permission denied\n");
  546.         }
  547.         if (setreuid(uid,euid) < 0 || getuid() != uid || geteuid() != euid)
  548.         fatal("Can't reswap uid and euid");
  549.         if (!cando(S_IXUSR,FALSE,&statbuf))        /* can real uid exec? */
  550.         fatal("Permission denied\n");
  551.     }
  552. #endif /* HAS_SETREUID */
  553. #endif /* IAMSUID */
  554.  
  555.     if (!S_ISREG(statbuf.st_mode))
  556.         fatal("Permission denied");
  557.     if (statbuf.st_mode & S_IWOTH)
  558.         fatal("Setuid/gid script is writable by world");
  559.     doswitches = FALSE;        /* -s is insecure in suid */
  560.     curcmd->c_line++;
  561.     if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
  562.       strnNE(tokenbuf,"#!",2) )    /* required even on Sys V */
  563.         fatal("No #! line");
  564.     s = tokenbuf+2;
  565.     if (*s == ' ') s++;
  566.     while (!isSPACE(*s)) s++;
  567.     if (strnNE(s-4,"perl",4) && strnNE(s-9,"perl",4))  /* sanity check */
  568.         fatal("Not a perl script");
  569.     while (*s == ' ' || *s == '\t') s++;
  570.     /*
  571.      * #! arg must be what we saw above.  They can invoke it by
  572.      * mentioning suidperl explicitly, but they may not add any strange
  573.      * arguments beyond what #! says if they do invoke suidperl that way.
  574.      */
  575.     len = strlen(validarg);
  576.     if (strEQ(validarg," PHOOEY ") ||
  577.         strnNE(s,validarg,len) || !isSPACE(s[len]))
  578.         fatal("Args must match #! line");
  579.  
  580. #ifndef IAMSUID
  581.     if (euid != uid && (statbuf.st_mode & S_ISUID) &&
  582.         euid == statbuf.st_uid)
  583.         if (!do_undump)
  584.         fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
  585. FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
  586. #endif /* IAMSUID */
  587.  
  588.     if (euid) {    /* oops, we're not the setuid root perl */
  589.         (void)fclose(rsfp);
  590. #ifndef IAMSUID
  591.         (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
  592.         execv(buf, origargv);    /* try again */
  593. #endif
  594.         fatal("Can't do setuid\n");
  595.     }
  596.  
  597.     if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid)
  598. #ifdef HAS_SETEGID
  599.         (void)setegid(statbuf.st_gid);
  600. #else
  601. #ifdef HAS_SETREGID
  602.         (void)setregid((GIDTYPE)-1,statbuf.st_gid);
  603. #else
  604.         setgid(statbuf.st_gid);
  605. #endif
  606. #endif
  607.     if (statbuf.st_mode & S_ISUID) {
  608.         if (statbuf.st_uid != euid)
  609. #ifdef HAS_SETEUID
  610.         (void)seteuid(statbuf.st_uid);    /* all that for this */
  611. #else
  612. #ifdef HAS_SETREUID
  613.         (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
  614. #else
  615.         setuid(statbuf.st_uid);
  616. #endif
  617. #endif
  618.     }
  619.     else if (uid)            /* oops, mustn't run as root */
  620. #ifdef HAS_SETEUID
  621.         (void)seteuid((UIDTYPE)uid);
  622. #else
  623. #ifdef HAS_SETREUID
  624.         (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
  625. #else
  626.         setuid((UIDTYPE)uid);
  627. #endif
  628. #endif
  629.     uid = (int)getuid();
  630.     euid = (int)geteuid();
  631.     gid = (int)getgid();
  632.     egid = (int)getegid();
  633.     if (!cando(S_IXUSR,TRUE,&statbuf))
  634.         fatal("Permission denied\n");    /* they can't do this */
  635.     }
  636. #ifdef IAMSUID
  637.     else if (preprocess)
  638.     fatal("-P not allowed for setuid/setgid script\n");
  639.     else
  640.     fatal("Script is not setuid/setgid in suidperl\n");
  641. #else
  642. #ifndef TAINT        /* we aren't taintperl or suidperl */
  643.     /* script has a wrapper--can't run suidperl or we lose euid */
  644.     else if (euid != uid || egid != gid) {
  645.     (void)fclose(rsfp);
  646.     (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
  647.     execv(buf, origargv);    /* try again */
  648.     fatal("Can't run setuid script with taint checks");
  649.     }
  650. #endif /* TAINT */
  651. #endif /* IAMSUID */
  652. #else /* !DOSUID */
  653. #ifndef TAINT        /* we aren't taintperl or suidperl */
  654.     if (euid != uid || egid != gid) {    /* (suidperl doesn't exist, in fact) */
  655. #ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
  656.     fstat(fileno(rsfp),&statbuf);    /* may be either wrapped or real suid */
  657.     if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
  658.         ||
  659.         (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
  660.        )
  661.         if (!do_undump)
  662.         fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
  663. FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
  664. #endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
  665.     /* not set-id, must be wrapped */
  666.     (void)fclose(rsfp);
  667.     (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
  668.     execv(buf, origargv);    /* try again */
  669.     fatal("Can't run setuid script with taint checks");
  670.     }
  671. #endif /* TAINT */
  672. #endif /* DOSUID */
  673.  
  674. #if !defined(IAMSUID) && !defined(TAINT)
  675.  
  676.     /* skip forward in input to the real script? */
  677.  
  678.     while (doextract) {
  679.     if ((s = str_gets(linestr, rsfp, 0)) == Nullch)
  680.         fatal("No Perl script found in input\n");
  681.     if (*s == '#' && s[1] == '!' && instr(s,"perl")) {
  682.         ungetc('\n',rsfp);        /* to keep line count right */
  683.         doextract = FALSE;
  684.         if (s = instr(s,"perl -")) {
  685.         s += 6;
  686.         /*SUPPRESS 530*/
  687.         while (s = moreswitches(s)) ;
  688.         }
  689.         if (cddir && chdir(cddir) < 0)
  690.         fatal("Can't chdir to %s",cddir);
  691.     }
  692.     }
  693. #endif /* !defined(IAMSUID) && !defined(TAINT) */
  694.  
  695.     defstab = stabent("_",TRUE);
  696.  
  697.     subname = str_make("main",4);
  698.     if (perldb) {
  699.     debstash = hnew(0);
  700.     stab_xhash(stabent("_DB",TRUE)) = debstash;
  701.     curstash = debstash;
  702.     dbargs = stab_xarray(aadd((tmpstab = stabent("args",TRUE))));
  703.     tmpstab->str_pok |= SP_MULTI;
  704.     dbargs->ary_flags = 0;
  705.     DBstab = stabent("DB",TRUE);
  706.     DBstab->str_pok |= SP_MULTI;
  707.     DBline = stabent("dbline",TRUE);
  708.     DBline->str_pok |= SP_MULTI;
  709.     DBsub = hadd(tmpstab = stabent("sub",TRUE));
  710.     tmpstab->str_pok |= SP_MULTI;
  711.     DBsingle = stab_val((tmpstab = stabent("single",TRUE)));
  712.     tmpstab->str_pok |= SP_MULTI;
  713.     DBtrace = stab_val((tmpstab = stabent("trace",TRUE)));
  714.     tmpstab->str_pok |= SP_MULTI;
  715.     DBsignal = stab_val((tmpstab = stabent("signal",TRUE)));
  716.     tmpstab->str_pok |= SP_MULTI;
  717.     curstash = defstash;
  718.     }
  719.  
  720.     /* init tokener */
  721.  
  722.     bufend = bufptr = str_get(linestr);
  723.  
  724.     savestack = anew(Nullstab);        /* for saving non-local values */
  725.     stack = anew(Nullstab);        /* for saving non-local values */
  726.     stack->ary_flags = 0;        /* not a real array */
  727.     afill(stack,63); afill(stack,-1);    /* preextend stack */
  728.     afill(savestack,63); afill(savestack,-1);
  729.  
  730.     /* now parse the script */
  731.  
  732.     error_count = 0;
  733.     if (yyparse() || error_count) {
  734.     if (minus_c)
  735.         fatal("%s had compilation errors.\n", origfilename);
  736.     else {
  737.         fatal("Execution of %s aborted due to compilation errors.\n",
  738.         origfilename);
  739.     }
  740.     }
  741.  
  742.     New(50,loop_stack,128,struct loop);
  743. #ifdef DEBUGGING
  744.     if (debug) {
  745.     New(51,debname,128,char);
  746.     New(52,debdelim,128,char);
  747.     }
  748. #endif
  749.     curstash = defstash;
  750.  
  751.     preprocess = FALSE;
  752.     if (e_fp) {
  753.     e_fp = Nullfp;
  754.     (void)UNLINK(e_tmpname);
  755.     }
  756.  
  757.     /* initialize everything that won't change if we undump */
  758.  
  759.     if (sigstab = stabent("SIG",allstabs)) {
  760.     sigstab->str_pok |= SP_MULTI;
  761.     (void)hadd(sigstab);
  762.     }
  763.  
  764.     magicalize("!#?^~=-%.+&*()<>,\\/[|`':\004\t\020\024\027\006");
  765.     userinit();        /* in case linked C routines want magical variables */
  766.  
  767.     amperstab = stabent("&",allstabs);
  768.     leftstab = stabent("`",allstabs);
  769.     rightstab = stabent("'",allstabs);
  770.     sawampersand = (amperstab || leftstab || rightstab);
  771.     if (tmpstab = stabent(":",allstabs))
  772.     str_set(STAB_STR(tmpstab),chopset);
  773.     if (tmpstab = stabent("\024",allstabs))
  774.     time(&basetime);
  775.  
  776.     /* these aren't necessarily magical */
  777.     if (tmpstab = stabent(";",allstabs))
  778.     str_set(STAB_STR(tmpstab),"\034");
  779.     if (tmpstab = stabent("]",allstabs)) {
  780.     str = STAB_STR(tmpstab);
  781.     str_set(str,rcsid);
  782.     str->str_u.str_nval = atof(patchlevel);
  783.     str->str_nok = 1;
  784.     }
  785.     str_nset(stab_val(stabent("\"", TRUE)), " ", 1);
  786.  
  787.     stdinstab = stabent("STDIN",TRUE);
  788.     stdinstab->str_pok |= SP_MULTI;
  789.     stab_io(stdinstab) = stio_new();
  790.     stab_io(stdinstab)->ifp = stdin;
  791.     tmpstab = stabent("stdin",TRUE);
  792.     stab_io(tmpstab) = stab_io(stdinstab);
  793.     tmpstab->str_pok |= SP_MULTI;
  794.  
  795.     tmpstab = stabent("STDOUT",TRUE);
  796.     tmpstab->str_pok |= SP_MULTI;
  797.     stab_io(tmpstab) = stio_new();
  798.     stab_io(tmpstab)->ofp = stab_io(tmpstab)->ifp = stdout;
  799.     defoutstab = tmpstab;
  800.     tmpstab = stabent("stdout",TRUE);
  801.     stab_io(tmpstab) = stab_io(defoutstab);
  802.     tmpstab->str_pok |= SP_MULTI;
  803.  
  804.     curoutstab = stabent("STDERR",TRUE);
  805.     curoutstab->str_pok |= SP_MULTI;
  806.     stab_io(curoutstab) = stio_new();
  807.     stab_io(curoutstab)->ofp = stab_io(curoutstab)->ifp = stderr;
  808.     tmpstab = stabent("stderr",TRUE);
  809.     stab_io(tmpstab) = stab_io(curoutstab);
  810.     tmpstab->str_pok |= SP_MULTI;
  811.     curoutstab = defoutstab;        /* switch back to STDOUT */
  812.  
  813.     statname = Str_new(66,0);        /* last filename we did stat on */
  814.  
  815.     /* now that script is parsed, we can modify record separator */
  816.  
  817.     rs = nrs;
  818.     rslen = nrslen;
  819.     rschar = nrschar;
  820.     str_nset(stab_val(stabent("/", TRUE)), rs, rslen);
  821.  
  822.     if (do_undump)
  823.     my_unexec();
  824.  
  825.   just_doit:        /* come here if running an undumped a.out */
  826.     argc--,argv++;    /* skip name of script */
  827.     if (doswitches) {
  828.     for (; argc > 0 && **argv == '-'; argc--,argv++) {
  829.         if (argv[0][1] == '-') {
  830.         argc--,argv++;
  831.         break;
  832.         }
  833.         if (s = index(argv[0], '=')) {
  834.         *s++ = '\0';
  835.         str_set(stab_val(stabent(argv[0]+1,TRUE)),s);
  836.         }
  837.         else
  838.         str_numset(stab_val(stabent(argv[0]+1,TRUE)),(double)1.0);
  839.     }
  840.     }
  841. #ifdef TAINT
  842.     tainted = 1;
  843. #endif
  844.     if (tmpstab = stabent("0",allstabs)) {
  845.     str_set(stab_val(tmpstab),origfilename);
  846.     magicname("0", Nullch, 0);
  847.     }
  848.     if (tmpstab = stabent("\030",allstabs))
  849.     str_set(stab_val(tmpstab),origargv[0]);
  850.     if (argvstab = stabent("ARGV",allstabs)) {
  851.     argvstab->str_pok |= SP_MULTI;
  852.     (void)aadd(argvstab);
  853.     aclear(stab_array(argvstab));
  854.     for (; argc > 0; argc--,argv++) {
  855.         (void)apush(stab_array(argvstab),str_make(argv[0],0));
  856.     }
  857.     }
  858. #ifdef TAINT
  859.     (void) stabent("ENV",TRUE);        /* must test PATH and IFS */
  860. #endif
  861.     if (envstab = stabent("ENV",allstabs)) {
  862.     envstab->str_pok |= SP_MULTI;
  863.     (void)hadd(envstab);
  864.     hclear(stab_hash(envstab), FALSE);
  865.     if (env != environ)
  866.         environ[0] = Nullch;
  867.     for (; *env; env++) {
  868.         if (!(s = index(*env,'=')))
  869.         continue;
  870.         *s++ = '\0';
  871.         str = str_make(s--,0);
  872.         str_magic(str, envstab, 'E', *env, s - *env);
  873.         (void)hstore(stab_hash(envstab), *env, s - *env, str, 0);
  874.         *s = '=';
  875.     }
  876.     }
  877. #ifdef TAINT
  878.     tainted = 0;
  879. #endif
  880.     if (tmpstab = stabent("$",allstabs))
  881.     str_numset(STAB_STR(tmpstab),(double)getpid());
  882.  
  883.     if (dowarn) {
  884.     stab_check('A','Z');
  885.     stab_check('a','z');
  886.     }
  887.  
  888.     if (setjmp(top_env))    /* sets goto_targ on longjump */
  889.     loop_ptr = -1;        /* start label stack again */
  890.  
  891. #ifdef DEBUGGING
  892.     if (debug & 1024)
  893.     dump_all();
  894.     if (debug)
  895.     fprintf(stderr,"\nEXECUTING...\n\n");
  896. #endif
  897.  
  898.     if (minus_c) {
  899.     fprintf(stderr,"%s syntax OK\n", origfilename);
  900.     exit(0);
  901.     }
  902.  
  903.     /* do it */
  904.  
  905.     (void) cmd_exec(main_root,G_SCALAR,-1);
  906.  
  907.     if (goto_targ)
  908.     fatal("Can't find label \"%s\"--aborting",goto_targ);
  909.     exit(0);
  910.     /* NOTREACHED */
  911. }
  912.  
  913. void
  914. magicalize(list)
  915. register char *list;
  916. {
  917.     char sym[2];
  918.  
  919.     sym[1] = '\0';
  920.     while (*sym = *list++)
  921.     magicname(sym, Nullch, 0);
  922. }
  923.  
  924. void
  925. magicname(sym,name,namlen)
  926. char *sym;
  927. char *name;
  928. int namlen;
  929. {
  930.     register STAB *stab;
  931.  
  932.     if (stab = stabent(sym,allstabs)) {
  933.     stab_flags(stab) = SF_VMAGIC;
  934.     str_magic(stab_val(stab), stab, 0, name, namlen);
  935.     }
  936. }
  937.  
  938. void
  939. savelines(array, str)
  940. ARRAY *array;
  941. STR *str;
  942. {
  943.     register char *s = str->str_ptr;
  944.     register char *send = str->str_ptr + str->str_cur;
  945.     register char *t;
  946.     register int line = 1;
  947.  
  948.     while (s && s < send) {
  949.     STR *tmpstr = Str_new(85,0);
  950.  
  951.     t = index(s, '\n');
  952.     if (t)
  953.         t++;
  954.     else
  955.         t = send;
  956.  
  957.     str_nset(tmpstr, s, t - s);
  958.     astore(array, line++, tmpstr);
  959.     s = t;
  960.     }
  961. }
  962.  
  963. /* this routine is in perl.c by virtue of being sort of an alternate main() */
  964.  
  965. int
  966. do_eval(str,optype,stash,savecmd,gimme,arglast)
  967. STR *str;
  968. int optype;
  969. HASH *stash;
  970. int savecmd;
  971. int gimme;
  972. int *arglast;
  973. {
  974.     STR **st = stack->ary_array;
  975.     int retval;
  976.     CMD *myroot = Nullcmd;
  977.     ARRAY *ar;
  978.     int i;
  979.     CMD * VOLATILE oldcurcmd = curcmd;
  980.     VOLATILE int oldtmps_base = tmps_base;
  981.     VOLATILE int oldsave = savestack->ary_fill;
  982.     VOLATILE int oldperldb = perldb;
  983.     SPAT * VOLATILE oldspat = curspat;
  984.     SPAT * VOLATILE oldlspat = lastspat;
  985.     static char *last_eval = Nullch;
  986.     static long last_elen = 0;
  987.     static CMD *last_root = Nullcmd;
  988.     VOLATILE int sp = arglast[0];
  989.     char *specfilename;
  990.     char *tmpfilename;
  991.     int parsing = 1;
  992.  
  993.     tmps_base = tmps_max;
  994.     if (curstash != stash) {
  995.     (void)savehptr(&curstash);
  996.     curstash = stash;
  997.     }
  998.     str_set(stab_val(stabent("@@",TRUE)),"");
  999.     if (curcmd->c_line == 0)        /* don't debug debugger... */
  1000.     perldb = FALSE;
  1001.     curcmd = &compiling;
  1002.     if (optype == O_EVAL) {        /* normal eval */
  1003.     curcmd->c_filestab = fstab("(eval)");
  1004.     curcmd->c_line = 1;
  1005.     str_sset(linestr,str);
  1006.     str_cat(linestr,";\n");        /* be kind to them */
  1007.     if (perldb)
  1008.         savelines(stab_xarray(curcmd->c_filestab), linestr);
  1009.     }
  1010.     else {
  1011.     if (last_root && !in_eval) {
  1012.         Safefree(last_eval);
  1013.         last_eval = Nullch;
  1014.         cmd_free(last_root);
  1015.         last_root = Nullcmd;
  1016.     }
  1017.     specfilename = str_get(str);
  1018.     str_set(linestr,"");
  1019.     if (optype == O_REQUIRE && &str_undef !=
  1020.       hfetch(stab_hash(incstab), specfilename, strlen(specfilename), 0)) {
  1021.         curcmd = oldcurcmd;
  1022.         tmps_base = oldtmps_base;
  1023.         st[++sp] = &str_yes;
  1024.         perldb = oldperldb;
  1025.         return sp;
  1026.     }
  1027.     tmpfilename = savestr(specfilename);
  1028.     if (index("/.", *tmpfilename))
  1029.         rsfp = fopen(tmpfilename,"r");
  1030.     else {
  1031.         ar = stab_array(incstab);
  1032.         for (i = 0; i <= ar->ary_fill; i++) {
  1033.         (void)sprintf(buf, "%s/%s",
  1034.           str_get(afetch(ar,i,TRUE)), specfilename);
  1035.         rsfp = fopen(buf,"r");
  1036.         if (rsfp) {
  1037.             char *s = buf;
  1038.  
  1039.             if (*s == '.' && s[1] == '/')
  1040.             s += 2;
  1041.             Safefree(tmpfilename);
  1042.             tmpfilename = savestr(s);
  1043.             break;
  1044.         }
  1045.         }
  1046.     }
  1047.     curcmd->c_filestab = fstab(tmpfilename);
  1048.     Safefree(tmpfilename);
  1049.     tmpfilename = Nullch;
  1050.     if (!rsfp) {
  1051.         curcmd = oldcurcmd;
  1052.         tmps_base = oldtmps_base;
  1053.         if (optype == O_REQUIRE) {
  1054.         sprintf(tokenbuf,"Can't locate %s in @@INC", specfilename);
  1055.         if (instr(tokenbuf,".h "))
  1056.             strcat(tokenbuf," (change .h to .ph maybe?)");
  1057.         if (instr(tokenbuf,".ph "))
  1058.             strcat(tokenbuf," (did you run h2ph?)");
  1059.         fatal("%s",tokenbuf);
  1060.         }
  1061.         if (gimme != G_ARRAY)
  1062.         st[++sp] = &str_undef;
  1063.         perldb = oldperldb;
  1064.         return sp;
  1065.     }
  1066.     curcmd->c_line = 0;
  1067.     }
  1068.     in_eval++;
  1069.     oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
  1070.     bufend = bufptr + linestr->str_cur;
  1071.     if (++loop_ptr >= loop_max) {
  1072.     loop_max += 128;
  1073.     Renew(loop_stack, loop_max, struct loop);
  1074.     }
  1075.     loop_stack[loop_ptr].loop_label = "_EVAL_";
  1076.     loop_stack[loop_ptr].loop_sp = sp;
  1077. #ifdef DEBUGGING
  1078.     if (debug & 4) {
  1079.     deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
  1080.     }
  1081. #endif
  1082.     eval_root = Nullcmd;
  1083.     if (setjmp(loop_stack[loop_ptr].loop_env)) {
  1084.     retval = 1;
  1085.     }
  1086.     else {
  1087.     error_count = 0;
  1088.     if (rsfp) {
  1089.         retval = yyparse();
  1090.         retval |= error_count;
  1091.     }
  1092.     else if (last_root && last_elen == bufend - bufptr
  1093.       && *bufptr == *last_eval && !bcmp(bufptr,last_eval,last_elen)){
  1094.         retval = 0;
  1095.         eval_root = last_root;    /* no point in reparsing */
  1096.     }
  1097.     else if (in_eval == 1 && !savecmd) {
  1098.         if (last_root) {
  1099.         Safefree(last_eval);
  1100.         last_eval = Nullch;
  1101.         cmd_free(last_root);
  1102.         }
  1103.         last_root = Nullcmd;
  1104.         last_elen = bufend - bufptr;
  1105.         last_eval = nsavestr(bufptr, last_elen);
  1106.         retval = yyparse();
  1107.         retval |= error_count;
  1108.         if (!retval)
  1109.         last_root = eval_root;
  1110.         if (!last_root) {
  1111.         Safefree(last_eval);
  1112.         last_eval = Nullch;
  1113.         }
  1114.     }
  1115.     else
  1116.         retval = yyparse();
  1117.     }
  1118.     myroot = eval_root;        /* in case cmd_exec does another eval! */
  1119.  
  1120.     if (retval) {
  1121.     st = stack->ary_array;
  1122.     sp = arglast[0];
  1123.     if (gimme != G_ARRAY)
  1124.         st[++sp] = &str_undef;
  1125.     if (parsing) {
  1126. #ifndef MANGLEDPARSE
  1127. #ifdef DEBUGGING
  1128.         if (debug & 128)
  1129.         fprintf(stderr,"Freeing eval_root %lx\n",(long)eval_root);
  1130. #endif
  1131.         cmd_free(eval_root);
  1132. #endif
  1133.         if ((CMD*)eval_root == last_root)
  1134.         last_root = Nullcmd;
  1135.         eval_root = myroot = Nullcmd;
  1136.     }
  1137.     if (rsfp) {
  1138.         fclose(rsfp);
  1139.         rsfp = 0;
  1140.     }
  1141.     }
  1142.     else {
  1143.     parsing = 0;
  1144.     sp = cmd_exec(eval_root,gimme,sp);
  1145.     st = stack->ary_array;
  1146.     for (i = arglast[0] + 1; i <= sp; i++)
  1147.         st[i] = str_mortal(st[i]);
  1148.                 /* if we don't save result, free zaps it */
  1149.     if (savecmd)
  1150.         eval_root = myroot;
  1151.     else if (in_eval != 1 && myroot != last_root)
  1152.         cmd_free(myroot);
  1153.     }
  1154.  
  1155.     perldb = oldperldb;
  1156.     in_eval--;
  1157. #ifdef DEBUGGING
  1158.     if (debug & 4) {
  1159.     char *tmps = loop_stack[loop_ptr].loop_label;
  1160.     deb("(Popping label #%d %s)\n",loop_ptr,
  1161.         tmps ? tmps : "" );
  1162.     }
  1163. #endif
  1164.     loop_ptr--;
  1165.     tmps_base = oldtmps_base;
  1166.     curspat = oldspat;
  1167.     lastspat = oldlspat;
  1168.     if (savestack->ary_fill > oldsave)    /* let them use local() */
  1169.     restorelist(oldsave);
  1170.  
  1171.     if (optype != O_EVAL) {
  1172.     if (retval) {
  1173.         if (optype == O_REQUIRE)
  1174.         fatal("%s", str_get(stab_val(stabent("@@",TRUE))));
  1175.     }
  1176.     else {
  1177.         curcmd = oldcurcmd;
  1178.         if (gimme == G_SCALAR ? str_true(st[sp]) : sp > arglast[0]) {
  1179.         (void)hstore(stab_hash(incstab), specfilename,
  1180.           strlen(specfilename), str_smake(stab_val(curcmd->c_filestab)),
  1181.               0 );
  1182.         }
  1183.         else if (optype == O_REQUIRE)
  1184.         fatal("%s did not return a true value", specfilename);
  1185.     }
  1186.     }
  1187.     curcmd = oldcurcmd;
  1188.     return sp;
  1189. }
  1190.  
  1191. int
  1192. do_try(cmd,gimme,arglast)
  1193. CMD *cmd;
  1194. int gimme;
  1195. int *arglast;
  1196. {
  1197.     STR **st = stack->ary_array;
  1198.  
  1199.     CMD * VOLATILE oldcurcmd = curcmd;
  1200.     VOLATILE int oldtmps_base = tmps_base;
  1201.     VOLATILE int oldsave = savestack->ary_fill;
  1202.     SPAT * VOLATILE oldspat = curspat;
  1203.     SPAT * VOLATILE oldlspat = lastspat;
  1204.     VOLATILE int sp = arglast[0];
  1205.  
  1206.     tmps_base = tmps_max;
  1207.     str_set(stab_val(stabent("@@",TRUE)),"");
  1208.     in_eval++;
  1209.     if (++loop_ptr >= loop_max) {
  1210.     loop_max += 128;
  1211.     Renew(loop_stack, loop_max, struct loop);
  1212.     }
  1213.     loop_stack[loop_ptr].loop_label = "_EVAL_";
  1214.     loop_stack[loop_ptr].loop_sp = sp;
  1215. #ifdef DEBUGGING
  1216.     if (debug & 4) {
  1217.     deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
  1218.     }
  1219. #endif
  1220.     if (setjmp(loop_stack[loop_ptr].loop_env)) {
  1221.     st = stack->ary_array;
  1222.     sp = arglast[0];
  1223.     if (gimme != G_ARRAY)
  1224.         st[++sp] = &str_undef;
  1225.     }
  1226.     else {
  1227.     sp = cmd_exec(cmd,gimme,sp);
  1228.     st = stack->ary_array;
  1229. /*    for (i = arglast[0] + 1; i <= sp; i++)
  1230.         st[i] = str_mortal(st[i]);  not needed, I think */
  1231.                 /* if we don't save result, free zaps it */
  1232.     }
  1233.  
  1234.     in_eval--;
  1235. #ifdef DEBUGGING
  1236.     if (debug & 4) {
  1237.     char *tmps = loop_stack[loop_ptr].loop_label;
  1238.     deb("(Popping label #%d %s)\n",loop_ptr,
  1239.         tmps ? tmps : "" );
  1240.     }
  1241. #endif
  1242.     loop_ptr--;
  1243.     tmps_base = oldtmps_base;
  1244.     curspat = oldspat;
  1245.     lastspat = oldlspat;
  1246.     curcmd = oldcurcmd;
  1247.     if (savestack->ary_fill > oldsave)    /* let them use local() */
  1248.     restorelist(oldsave);
  1249.  
  1250.     return sp;
  1251. }
  1252.  
  1253. /* This routine handles any switches that can be given during run */
  1254.  
  1255. static char *
  1256. moreswitches(s)
  1257. char *s;
  1258. {
  1259.     int numlen;
  1260.  
  1261.     switch (*s) {
  1262.     case '0':
  1263.     nrschar = scanoct(s, 4, &numlen);
  1264.     nrs = nsavestr("\n",1);
  1265.     *nrs = nrschar;
  1266.     if (nrschar > 0377) {
  1267.         nrslen = 0;
  1268.         nrs = "";
  1269.     }
  1270.     else if (!nrschar && numlen >= 2) {
  1271.         nrslen = 2;
  1272.         nrs = "\n\n";
  1273.         nrschar = '\n';
  1274.     }
  1275.     return s + numlen;
  1276.     case 'a':
  1277.     minus_a = TRUE;
  1278.     s++;
  1279.     return s;
  1280.     case 'c':
  1281.     minus_c = TRUE;
  1282.     s++;
  1283.     return s;
  1284.     case 'd':
  1285. #ifdef TAINT
  1286.     if (euid != uid || egid != gid)
  1287.         fatal("No -d allowed in setuid scripts");
  1288. #endif
  1289.     perldb = TRUE;
  1290.     s++;
  1291.     return s;
  1292.     case 'D':
  1293. #ifdef DEBUGGING
  1294. #ifdef TAINT
  1295.     if (euid != uid || egid != gid)
  1296.         fatal("No -D allowed in setuid scripts");
  1297. #endif
  1298.     debug = atoi(s+1) | 32768;
  1299. #else
  1300.     warn("Recompile perl with -DDEBUGGING to use -D switch\n");
  1301. #endif
  1302.     /*SUPPRESS 530*/
  1303.     for (s++; isDIGIT(*s); s++) ;
  1304.     return s;
  1305.     case 'i':
  1306.     inplace = savestr(s+1);
  1307.     /*SUPPRESS 530*/
  1308.     for (s = inplace; *s && !isSPACE(*s); s++) ;
  1309.     *s = '\0';
  1310.     break;
  1311.     case 'I':
  1312. #ifdef TAINT
  1313.     if (euid != uid || egid != gid)
  1314.         fatal("No -I allowed in setuid scripts");
  1315. #endif
  1316.     if (*++s) {
  1317.         (void)apush(stab_array(incstab),str_make(s,0));
  1318.     }
  1319.     else
  1320.         fatal("No space allowed after -I");
  1321.     break;
  1322.     case 'l':
  1323.     minus_l = TRUE;
  1324.     s++;
  1325.     if (isDIGIT(*s)) {
  1326.         ors = savestr("\n");
  1327.         orslen = 1;
  1328.         *ors = scanoct(s, 3 + (*s == '0'), &numlen);
  1329.         s += numlen;
  1330.     }
  1331.     else {
  1332.         ors = nsavestr(nrs,nrslen);
  1333.         orslen = nrslen;
  1334.     }
  1335.     return s;
  1336.     case 'n':
  1337.     minus_n = TRUE;
  1338.     s++;
  1339.     return s;
  1340.     case 'p':
  1341.     minus_p = TRUE;
  1342.     s++;
  1343.     return s;
  1344.     case 'u':
  1345.     do_undump = TRUE;
  1346.     s++;
  1347.     return s;
  1348.     case 'U':
  1349.     unsafe = TRUE;
  1350.     s++;
  1351.     return s;
  1352.     case 'v':
  1353.     fputs("\nThis is perl, version 4.0\n\n",stdout);
  1354.     fputs(rcsid,stdout);
  1355.     fputs("\nCopyright (c) 1989, 1990, 1991, Larry Wall\n",stdout);
  1356. #ifdef MSDOS
  1357.     fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
  1358.     stdout);
  1359. #ifdef OS2
  1360.         fputs("OS/2 port Copyright (c) 1990, Raymond Chen, Kai Uwe Rommel\n",
  1361.         stdout);
  1362. #endif
  1363. #endif
  1364.     fputs("\n\
  1365. Perl may be copied only under the terms of either the Artistic License or the\n\
  1366. GNU General Public License, which may be found in the Perl 4.0 source kit.\n",stdout);
  1367. #ifdef MSDOS
  1368.         usage(origargv[0]);
  1369. #endif
  1370.     exit(0);
  1371.     case 'w':
  1372.     dowarn = TRUE;
  1373.     s++;
  1374.     return s;
  1375.     case ' ':
  1376.     case '\n':
  1377.     case '\t':
  1378.     break;
  1379.     default:
  1380.     fatal("Switch meaningless after -x: -%s",s);
  1381.     }
  1382.     return Nullch;
  1383. }
  1384.  
  1385. /* compliments of Tom Christiansen */
  1386.  
  1387. /* unexec() can be found in the Gnu emacs distribution */
  1388.  
  1389. my_unexec()
  1390. {
  1391. #ifdef UNEXEC
  1392.     int    status;
  1393.     extern int etext;
  1394.     static char dumpname[BUFSIZ];
  1395.     static char perlpath[256];
  1396.  
  1397.     sprintf (dumpname, "%s.perldump", origfilename);
  1398.     sprintf (perlpath, "%s/perl", BIN);
  1399.  
  1400.     status = unexec(dumpname, perlpath, &etext, sbrk(0), 0);
  1401.     if (status)
  1402.     fprintf(stderr, "unexec of %s into %s failed!\n", perlpath, dumpname);
  1403.     exit(status);
  1404. #else
  1405. #ifdef MSDOS
  1406.     abort();    /* nothing else to do */
  1407. #else /* ! MSDOS */
  1408. #   ifndef SIGABRT
  1409. #    define SIGABRT SIGILL
  1410. #   endif
  1411. #   ifndef SIGILL
  1412. #    define SIGILL 6        /* blech */
  1413. #   endif
  1414.     kill(getpid(),SIGABRT);    /* for use with undump */
  1415. #endif /* ! MSDOS */
  1416. #endif
  1417. }
  1418.  
  1419. @
  1420.  
  1421.  
  1422. 1.2
  1423. log
  1424. @we use some sort of non-standard sed
  1425. @
  1426. text
  1427. @d1 1
  1428. a1 1
  1429. char rcsid[] = "$RCSfile: perl.c,v $$Revision: 1.1 $$Date: 91/07/16 12:16:14 $\nPatch level: ###\n";
  1430. d9 16
  1431. d48 2
  1432. d88 1
  1433. d218 4
  1434. d241 1
  1435. d245 1
  1436. a245 1
  1437.     argv[0] = e_tmpname;
  1438. d289 1
  1439. a289 1
  1440.     if (argv[0] == Nullch)
  1441. d294 1
  1442. a294 1
  1443.     argv[0] = "-";
  1444. d297 1
  1445. a297 1
  1446.     argv[0] = "-";
  1447. d299 1
  1448. a299 1
  1449.     if (dosearch && !index(argv[0], '/') && (s = getenv("PATH"))) {
  1450. d319 1
  1451. a319 1
  1452.         (void)strcat(tokenbuf+len,argv[0]);
  1453. d335 1
  1454. a335 1
  1455.         fatal("Can't execute %s", xfailed ? xfailed : argv[0] );
  1456. d338 1
  1457. a338 1
  1458.     argv[0] = savestr(xfound);
  1459. d344 1
  1460. a344 1
  1461.     origfilename = savestr(argv[0]);
  1462. d347 1
  1463. a347 1
  1464.     argv[0] = "";
  1465. d349 6
  1466. d381 2
  1467. d384 1
  1468. a384 1
  1469.  -e 's/^#.*//' \
  1470. d392 1
  1471. a392 1
  1472.       argv[0], CPPSTDIN, str_get(str), CPPMINUS);
  1473. d415 5
  1474. a419 1
  1475.     else if (!*argv[0])
  1476. d421 1
  1477. d423 2
  1478. a424 2
  1479.     rsfp = fopen(argv[0],"r");
  1480.     if (rsfp == Nullfp) {
  1481. d533 1
  1482. a533 1
  1483.     while (!isspace(*s)) s++;
  1484. d544 1
  1485. a544 1
  1486.         strnNE(s,validarg,len) || !isspace(s[len]))
  1487. d653 1
  1488. d664 1
  1489. a671 1
  1490.     subname = str_make("main",4);
  1491. d933 1
  1492. a933 1
  1493. do_eval(str,optype,stash,gimme,arglast)
  1494. d937 1
  1495. d953 1
  1496. d1059 2
  1497. a1060 1
  1498.     else if (last_root && *bufptr == *last_eval && strEQ(bufptr,last_eval)){
  1499. d1064 1
  1500. a1064 1
  1501.     else if (in_eval == 1) {
  1502. d1071 2
  1503. a1072 1
  1504.         last_eval = savestr(bufptr);
  1505. d1100 1
  1506. a1100 1
  1507.         if (eval_root == last_root)
  1508. d1116 3
  1509. a1118 1
  1510.     if (in_eval != 1 && myroot != last_root)
  1511. d1158 62
  1512. a1227 1
  1513.   reswitch:
  1514. d1269 2
  1515. a1270 1
  1516.     for (s++; isdigit(*s); s++) ;
  1517. d1274 2
  1518. a1275 1
  1519.     for (s = inplace; *s && !isspace(*s); s++) ;
  1520. d1292 1
  1521. a1292 1
  1522.     if (isdigit(*s)) {
  1523. @
  1524.  
  1525.  
  1526. 1.1
  1527. log
  1528. @Initial revision
  1529. @
  1530. text
  1531. @d1 1
  1532. a1 1
  1533. char rcsid[] = "$RCSfile: perl.c,v $$Revision: 4.0.1.4 $$Date: 91/06/10 01:23:07 $\nPatch level: ###\n";
  1534. d9 3
  1535. d327 16
  1536. d367 1
  1537. @
  1538.